#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include<signal.h>
#include<functional>
#include"log.hpp"
#include"Protocol.hpp"

using namespace std;

namespace server
{enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };
    //构建函数的指针
 typedef std::function<bool(const Request &req ,Response &resp)> func_t;

 void Handler(int sock, func_t func) // 放类外面为了解耦，可以更改方法
 {                                   // 1.保证消息完整性：读取
   static string inbuffer;

   while (true)//为了不停的进行通信
   {
     string package;
     if (!recvpackage(sock, inbuffer, &package))
       return;
      string recv;
     if(!delength(package,&recv)) return ;  
     // 2.怎么处理报文：反序列化，得到结构化对象
     Request req;
     if (!req.deserialize(recv))
       return;
     // 对结构化对象做处理
     // 3.得到结构化的响应(响应需要对返回结构体做更改，因此可以用函数进行更改，这个函数可以通过外部进行传递)
     Response resp;
     func(req, resp);
     // 4.对响应转化为报文（字符串）：序列化
     string resp_str;
     resp.serialize(&resp_str);
     std::cout << "计算完成, 序列化响应: " <<  resp_str << std::endl;
     // 5.对发送的字符串做处理，加上字符串大小的前缀以及分隔符
     string send_string =enlength(resp_str);
     std::cout << "构建完成完整的响应\n" <<  send_string << std::endl;
     send(sock,send_string.c_str(),send_string.size(),0);
   }
 }
  static const uint16_t gport=8080;
  static const int gbacklog=5;
  //static const std::string ip="0.0.0.0";
  class Calserver
  { public:
     Calserver(const uint16_t &port=gport):_listensock(-1),_port(port)
{}
    void initServer()
    {   //1.创建套接字
        _listensock=socket(AF_INET,SOCK_STREAM,0);
        if(_listensock<0)
        {
            logMessage(FATAL, "create socket error");
                exit(SOCKET_ERR);
        }
        logMessage(NORMAL,"create socket success");
        //2.绑定服务端的网络信息到结构体上
           struct sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;//任意ip
            if (bind(_listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
            {
                logMessage(FATAL, "bind socket error");
                exit(BIND_ERR);
            }
            logMessage(NORMAL, "bind socket success");
            //3.设置套接字为监听状态
            if(listen(_listensock,gbacklog)<0)
            {
                logMessage(FATAL, "listen socket error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL,"listensocket success");
    }
    void start(func_t func)
    { 
      for(;;)
      {
        //4.获取链接
        struct sockaddr_in peer;
        socklen_t len=sizeof(peer);
        //建立链接是在accept之前，客户端os发出链接请求，服务端os接受
        int sock =accept(_listensock,(struct sockaddr*)&peer,&len);//sock为得到客户端传递信息的文件描述符
        if(sock<0)
        {
            logMessage(ERROR, "accept error, next");
                    continue;

        }
        logMessage(NORMAL, "accept success 文件描述符：%d", sock);
        logMessage(ERROR, "accept error, next");
        logMessage(FATAL, "fatal error, next");
        logMessage(DEBUG, "测试 error, next");
        logMessage(WARNING, "警告, next");
        logMessage(ERROR, "错误, next");

          int n =fork();
          if(n==0)
          {close(_listensock);
          Handler(sock,func);
          close(sock);
          exit(0);
          }
          close(sock);
        

       }
      
    }
   
  
   ~Calserver(){}

    private:
    int _listensock;
    uint16_t _port;
  };




}
